import yaml
import copy
from datetime import datetime
from tools.byte_track import ByteTrackLite
from detect.detect import Detect
import time
import numpy as np
import os
from tools.log import logger
class Detector:
    def __init__(self,global_conf,camera_conf):
        self.camera_conf=camera_conf
        self.global_conf=global_conf
        self.detect_conf = copy.deepcopy(camera_conf["detect"])
        self.detect_conf["model"]=global_conf["environment"]+self.detect_conf["model"]
        self.rknn = Detect(self.detect_conf)
        self.prefix =self.global_conf["box"]["id"]+"_"+self.camera_conf["id"]
        self.positive_vec = self.detect_conf["bus"]["positive_vec"]
        self.bytetracker=ByteTrackLite(iou_thresh=self.detect_conf["bus"]["iou"],roi_list=self.detect_conf["bus"]["roi_list"],max_age=20)
        self.loaded=False

    def init_info(self,frame):
        self.rknn.load_frame_info(frame) #初始化参数

    def reflex(self,boxes,classes,scores):
                # 1. 减去填充（向量化操作）
        boxes[:, [0, 2]] -= self.rknn.padding_w  # 所有框的 x1, x2
        boxes[:, [1, 3]] -= self.rknn.padding_h  # 所有框的 y1, y2

        # 2. 限制边界
        boxes[:, [0, 2]] = np.clip(boxes[:, [0, 2]], 0, self.rknn.target_w - 2 * self.rknn.padding_w)
        boxes[:, [1, 3]] = np.clip(boxes[:, [1, 3]], 0, self.rknn.target_h - 2 * self.rknn.padding_h)

            # 3. 缩放
        boxes /= self.rknn.scale
            # 宽高最小值保证
        w = boxes[:,2] - boxes[:,0]
        h = boxes[:,3] - boxes[:,1]

        # 修正 w/h <=0 的框
        valid = np.where((w > 3) & (h > 3))
        boxes = boxes[valid]
        classes = classes[valid]
        scores = scores[valid]
            # 4. 面积占比过滤（画面面积）
        frame_area = 921600   # 1280*720
        box_area = w * h
        ratio = box_area / frame_area

        valid2 = np.where(ratio <= 0.35)   # 只保留 <=35%的框
        boxes = boxes[valid2]
        classes = classes[valid2]
        scores = scores[valid2]
        return boxes,classes,scores
    @staticmethod    
    def gen_from_timestamp():
       # 如果没有提供 timestamp，就用当前时间
        # 转换为 datetime 对象
        dt = datetime.fromtimestamp(time.time())
        # 格式化输出
        return f"{dt:%Y%m%d_%H%M%S}{dt.microsecond//1000:03d}"
    @staticmethod    
    def genalarm(timestamp):
       # 如果没有提供 timestamp，就用当前时间
        if timestamp is None:
            timestamp = time.time()
        # 转换为 datetime 对象
        dt = datetime.fromtimestamp(timestamp)
        formatted = dt.strftime("%Y-%m-%d %H:%M:%S")
        # 格式化输出
        return formatted
    @staticmethod
    def read_add(file):
        with open(file, 'r+') as file:
            try:
                num = int(file.read())
            except ValueError:
                num = 0
            file.seek(0)
            file.write(str(num + 1))
            file.truncate()
            return num
        return 0 
    
    @staticmethod
    def write_meta(file,meta_yaml):
        with open(file,"w",encoding='utf-8') as wd:
            yaml.safe_dump(meta_yaml,wd)

    def make_and_load_meta(self,ts)->dict:
        ts_fmt = self.gen_from_timestamp()
        idx = self.prefix+"_"+ts_fmt

        meta_template = {
            "id":  idx,
            "record": self.read_add(self.global_conf["environment"]+self.camera_conf['record']),
            "box": self.global_conf["box"],
            "camera_id": self.camera_conf["id"],
            "time": ts,
            "image": f"{idx}.bmp",
            "video": f"{idx}.mp4",
            "alarm": self.genalarm(ts),
            "vehicle":None,
            "ready": False, #是否完成上传准备
            "direction":0,
            "only_image":False,
            "position":self.camera_conf["position"]
        }
        meta_template["dir"] = self.global_conf["environment"]+self.global_conf["temp"]["data"]+meta_template['id']+"/"
        os.makedirs(meta_template["dir"] ,exist_ok=True)
        return meta_template
    
    @staticmethod
    def transform_boxes(boxes, scale, padwh, img_size):
        """
        Args:
            boxes: [[x1, y1, x2, y2], ...]  # 多个框的列表或 NumPy 数组
            ratio, padwh, img_size: 同单个框
        Returns:
            transformed_boxes: 变换后的所有框
        """
        boxes = np.array(boxes, dtype=np.float32)
        padw, padh = padwh
        imgw, imgh = img_size
        
        # 1. 缩放
        boxes *= scale
        # 2. 减去填充（向量化操作）
        boxes[:, [0, 2]] -= padw  # 所有框的 x1, x2
        boxes[:, [1, 3]] -= padh  # 所有框的 y1, y2

        # 3. 限制边界
        boxes[:, [0, 2]] = np.clip(boxes[:, [0, 2]], 0, imgw - 2 * padw)
        boxes[:, [1, 3]] = np.clip(boxes[:, [1, 3]], 0, imgh - 2 * padh)

        return boxes.astype(np.int32)

